/*
 * CMediaRender.cpp
 *
 *  Created on: 2017年3月16日
 *      Author: chuanjiang.zh
 */

#include "CMediaRender.h"
#include "MFormatUtil.h"
#include "CVideoRender.h"
#include "CAudioRender.h"

#include "CVideoDecoder.h"
#include "CAudioDecoder.h"
#include "FfmpegUtil.h"


namespace av
{


CMediaRender::CMediaRender(void* wnd):
		m_wnd(wnd),
		m_videoRender(new CVideoRender()),
		m_audioRender(new CAudioRender()),
		m_state()
{
	m_videoDecoder.reset(new CVideoDecoder());
	m_audioDecoder.reset(new CAudioDecoder());

	m_videoRender->create(m_wnd);

}

CMediaRender::~CMediaRender()
{
	close();

	m_videoRender->destroy();
}

int CMediaRender::open(const MFormat& fmt)
{
	MFormatUtil::copyTo(&fmt, m_format);

	m_videoDecoder->open(m_format);
	m_audioDecoder->open(m_format);

	m_videoRender->open(m_format);
	m_audioRender->open(m_format.m_channels, m_format.m_sampleRate, AV_SAMPLE_FMT_S16);

	return 0;
}

void CMediaRender::close()
{
	m_videoDecoder->close();
	m_audioDecoder->close();

	m_audioRender->close();
	m_videoRender->close();
}

bool CMediaRender::isOpen()
{
	return true;
}

int CMediaRender::write(MPacket& pkt)
{
	AVPacketPtr avpkt(new AVPacket());
	avpkt->data = pkt.data;
	avpkt->size = pkt.size;
	avpkt->pts = pkt.pts;
	avpkt->dts = pkt.pts;
	avpkt->duration = pkt.duration;
	avpkt->flags = pkt.flags;

	AVFramePtr frame(av_frame_alloc(), ffmpeg::AVFrameDeleter());

	int rc = 0;
	if (pkt.type == MEDIA_TYPE_VIDEO)
	{
		if (m_videoDecoder->decode(avpkt, frame))
		{
			m_videoRender->write(frame.get());
		}
	}
	else if (pkt.type == MEDIA_TYPE_AUDIO)
	{
		if (m_audioDecoder->decode(avpkt, frame))
		{
			m_audioRender->write(frame.get());
		}
	}

	return 0;
}

int CMediaRender::play()
{
	setState(STATE_PLAYING);

	m_videoRender->play();
	m_audioRender->play();

	return 0;
}

int CMediaRender::pause()
{
	setState(STATE_PAUSED);

	m_videoRender->pause();
	m_audioRender->pause();

	return 0;
}

void CMediaRender::stop()
{
	setState(STATE_STOPPED);

	m_videoRender->stop();
	m_audioRender->stop();
}

void CMediaRender::flush()
{
	m_videoRender->flush();
	m_audioRender->flush();
}

int CMediaRender::getState()
{
	return m_state;
}

void CMediaRender::setState(int state)
{
	m_state = (StreamState)state;

}



} /* namespace av */
